#ifndef _REG_TOKEN_IMPL
#define _REG_TOKEN_IMPL

#include "Reg_token.h"
#include "Algorithm.h"
using namespace dfa_lex;

/* implement class Token {
		mylib::Buffer *in_str;	// the input stream
		std::string lexeme;
		Reg_token token_type;
*/
Reg_token Token::get() {
	if( !in_str )			//
		return Token::token_type;
get_next_token:
	char c;
	if( !in_str->get(c) ) {
		lexeme.clear();
		token_type = dfa_lex::END;
		return token_type;
	}
	switch(c)  {
	case '<' :
		lexeme = "<";
		token_type = dfa_lex::LEFT_BRACKET;
		break;
	case '>' :
		lexeme = ">";
		token_type = dfa_lex::RIG_BRACKET;
		break;
	case '^' :
		lexeme = "^";
		token_type = dfa_lex::REV;
		break;
	case '"' :
		in_str->ret();
		lexeme.clear();
		mylib::get_str(*in_str, lexeme);
		token_type = dfa_lex::STR;
		break;
	case '\\' :			 // escape character
		char ch;
		mylib::get_escape_char(*in_str, ch);
		lexeme.clear();
		lexeme += ch;
		token_type = dfa_lex::NOR_CHAR;
		break;
	case '.' :
		lexeme = ".";
		token_type = dfa_lex::DOT;
		break;
	case '[' :
		lexeme =  "[";
		token_type = dfa_lex::LEFT_BRACE;
		break;
	case ']':
		lexeme = "]";
		token_type = dfa_lex::RIG_BRACE;
		break;
	case '(' :
		lexeme = "(";
		token_type = dfa_lex::LEFT_PAR;
		break;
	case ')' :
		lexeme = ")";
		token_type = dfa_lex::RIG_PAR;
		break;
	case '{':
		lexeme = "{";
		in_times=true;					// in {int, int}, or {id}
		token_type = dfa_lex::LEFT_BIG;
		break;
	case '}':
		lexeme = "}";					// out times
		in_times=false;
		token_type = dfa_lex::RIG_BIG;
		break;
	case '*' :
		lexeme = "*";
		token_type = dfa_lex::KLEEN;
		break;
	case '+' :
		lexeme = "+";
		token_type = dfa_lex::ONE_MORE;
		break;
	case '?' :
		lexeme = "?";
		token_type = dfa_lex::ZERO_ONE;
		break;
	case ',' :
		lexeme = ",";
		token_type = dfa_lex::COMMA;
		break;
	case '|' :
		lexeme = "|";
		token_type = dfa_lex::OR;
		break;
	case '/' :
		lexeme = "/";
		token_type = dfa_lex::SUFFIX;
		break;
	case '$' :
		lexeme = "$";
		token_type = dfa_lex::END_LINE;
		break;
	default: {
		bool end=false;
		if( isspace(c) ) {
			do { if( !in_str->get(c) ) {end=true; break;}
			} while( isspace(c) );
			if( !end )
				in_str->ret();
			if( in_times )
				goto get_next_token;
			lexeme.clear();
			token_type = dfa_lex::END;
		} else if( (isalpha(c) || c == '_') && token_type == dfa_lex::LEFT_BIG) {	// must to match '{' id '}'
			token_type = dfa_lex::ID;
			lexeme.clear();
			do {
				lexeme += c;
				if( !in_str->get(c) ) {
					end=true;
					break;
				}
			} while( isalnum(c) || c == '_' );
			if( !end )
				in_str->ret();
		} else if( isdigit(c) && in_times ) {
			token_type = dfa_lex::INT;
			lexeme.clear();
			do {
				lexeme += c;
				if( !in_str->get(c) ) {
					end=true;
					break;
				}
			} while( isdigit(c) );
			if( !end )
				in_str->ret();
		} else if( c < 0 || c >= 128 ) {
			lexeme.clear();
			lexeme += c;
			token_type = dfa_lex::UNDEF;
		} else {
			lexeme.clear();
			lexeme += c;
			token_type = dfa_lex::NOR_CHAR;
		}
		break;	}
	}
	return token_type;
}
#endif
